﻿using System;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Options;
using Simple.Common.EntityFrameworkCore.Entities;

namespace Simple.Common.EntityFrameworkCore.EntityFrameworkCore
{
    public class EFDbContext<TDbContext> : DbContext where TDbContext : EFDbContext<TDbContext>
    {
        public EFDbContext() : base(new DbContextOptions<TDbContext>())
        {
        }

        // 控制台日志输出
        protected static readonly LoggerFactory myLoggerFactory = new LoggerFactory(new[] { new ConsoleLoggerProvider(GetOptionsMonitor()) });

        private static OptionsMonitor<ConsoleLoggerOptions> GetOptionsMonitor()
        {
            var configureNamedOptions = new ConfigureNamedOptions<ConsoleLoggerOptions>("", null);
            var optionsFactory = new OptionsFactory<ConsoleLoggerOptions>(new[] { configureNamedOptions }, Enumerable.Empty<IPostConfigureOptions<ConsoleLoggerOptions>>());
            var optionsMonitor = new OptionsMonitor<ConsoleLoggerOptions>(optionsFactory, Enumerable.Empty<IOptionsChangeTokenSource<ConsoleLoggerOptions>>(), new OptionsCache<ConsoleLoggerOptions>());
            return optionsMonitor;
        }
        protected override void OnModelCreating(ModelBuilder builder)
        {
            foreach (var entityType in builder.Model.GetEntityTypes()
                    .Where(e => typeof(IDeleteAggregateRoot).IsAssignableFrom(e.ClrType)))
            {
                builder.Entity(entityType.ClrType).Property<Boolean>("IsDeleted");
                var parameter = Expression.Parameter(entityType.ClrType, "e");
                var body = Expression.Equal(
                    Expression.Call(typeof(EF), nameof(EF.Property), new[] { typeof(bool) }, parameter, Expression.Constant("IsDeleted")),
                    Expression.Constant(false));
                builder.Entity(entityType.ClrType).HasQueryFilter(Expression.Lambda(body, parameter));
            }
            base.OnModelCreating(builder);
        }
    }
}